package com.todod.service;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.todod.common.util.ESData;
import com.todod.dto.EsSortDto;
import com.todod.dto.PublicFileDto;
import com.todod.entity.EsQuery;
import com.todod.entity.Page;
import com.todod.mapper.PublicFileMapper;
import com.todod.model.PublicFile;
import com.todod.model.PublicFileQuantity;
import com.todod.model.User;

@Service
public class ESClientSearchService {
	@Autowired
	private ElasticsearchService elasticsearchService;
	@Autowired
	private PublicFileMapper publicFileMapper;
	@Autowired
	private IUserService iUserService;
	@Autowired
	private PublicFileService publicFileService;
	@Autowired
	public PublicFileQuantityService publicFileQuantityService;

	/**
	 * 统计条数
	 * 
	 * @Title: queryCount
	 * @Description:
	 * @author gsh
	 * @date 2020年5月22日
	 * @param index
	 * @param key
	 * @return
	 * @throws IOException
	 */
	public long queryCount(String index, String key) throws IOException {
		long count = elasticsearchService.queryCount(index, key);

		return count;
	}

	/**
	 * 总数
	 * 
	 * @param index
	 * @return
	 * @throws Exception
	 */
	public Long total(String index) throws Exception {
		Long total = elasticsearchService.total(index);
		return total;

	}

	/**
	 * 柱状图查询
	 * 
	 * @param index
	 * @param key
	 * @param fields
	 * @return
	 * @throws Exception
	 */
	public List<EsSortDto> sortfield(String index, String key, String fields) throws Exception {
		List<EsSortDto> list = elasticsearchService.getinfo3(index, key, fields);
		return list;
	}

	/**
	 * 部门文档查询
	 * 
	 * @Title: queryBmwd
	 * @Description:
	 * @author gsh
	 * @param departId
	 * @date 2020年5月27日
	 * @param esQuery
	 * @return
	 * @throws IOException
	 */
	public Page<Map<String, Object>> queryBmwd(Long departId, EsQuery esQuery) throws IOException {
		List<String> highlights = getHighlights(ESData.BMWD_INDEX);
		esQuery.setHighlights(highlights); // 高亮字段

		SearchResponse response = elasticsearchService.query(ESData.BMWD_INDEX, esQuery, null, departId);

		Page<Map<String, Object>> page = getPage(response);
//		List<Map<String, Object>> list = page.getRecords();
//		list.stream().forEach(Object -> {
//			System.out.println(Object.toString());
//		});

		return page;
	}

	/**
	 * 个人文档查询
	 * 
	 * @Title: queryJgk
	 * @Description:
	 * @author gsh
	 * @date 2020年5月26日
	 * @param esQuery
	 * @return
	 * @throws IOException
	 */
	public Page<Map<String, Object>> queryGrwd(Long userId, Long departId, EsQuery esQuery) throws IOException {
		List<String> highlights = getHighlights(ESData.GRWD_INDEX);
		esQuery.setHighlights(highlights); // 高亮字段

		SearchResponse response = elasticsearchService.query(ESData.GRWD_INDEX, esQuery, userId, departId);

		Page<Map<String, Object>> page = getPage(response);
		List<Map<String, Object>> list = page.getRecords();
		list.stream().forEach(Object -> {
			System.out.println(Object.toString());
		});

		return page;
	}

	/**
	 * 获取分页
	 * 
	 * @Title: getPage
	 * @Description:
	 * @author gsh
	 * @date 2020年5月22日
	 * @param response
	 * @return
	 */
	private Page<Map<String, Object>> getPage(SearchResponse response) {
		SearchHits hits = response.getHits();

		Page<Map<String, Object>> page = new Page<Map<String, Object>>();
		page.setTotal(hits.getTotalHits().value);// 总条数
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		for (SearchHit searchHit : hits) {
			Map<String, Object> source = searchHit.getSourceAsMap();

			// 高亮替换
			Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
			Set<String> highlightSet = highlightFields.keySet();
			for (String highlight : highlightSet) {
				HighlightField titleField = highlightFields.get(highlight);
				if (titleField != null) {
					Text[] fragments = titleField.fragments();
					String name = "";
					for (Text text : fragments) {
						name += text;
					}
					source.put(highlight, name); // 高亮字段替换掉原本的内容
				}
			}
			list.add(source);
		}
		page.setRecords(list);

		return page;
	}

	/**
	 * 高亮字段
	 * 
	 * @param flag
	 * @return
	 */
	private List<String> getHighlights(String flag) {
		List<String> highlights = new ArrayList<String>();
		if (ESData.BMWD_INDEX.equals(flag)) {
			highlights.add("fileName");
			highlights.add("fileLabel");

		} else if (ESData.GRWD_INDEX.equals(flag)) {
			highlights.add("fileName");
			highlights.add("fileLabel");

		}

		return highlights;
	}

	/**
	 * 
	 * @param esQuery
	 * @return
	 * @throws IOException
	 * @throws ParseException
	 */
	public Map<String, Object> searchTopNumber(Long departId) throws IOException, ParseException {
		Map<String, Object> map = new HashMap<>();
		String date = LocalDateTime.now().toString();
		String date1 = date.substring(0, 10);
		// 获取文档总量
		long count1 = elasticsearchService.queryTypeFiles(ESData.BMWD_INDEX, null, departId);
		long count2 = elasticsearchService.queryTypeFiles(ESData.GRWD_INDEX, null, departId);
		// 获取今日已上传文档
		long count3 = elasticsearchService.queryTypeFiles(ESData.BMWD_INDEX, date1, departId);
		long count4 = elasticsearchService.queryTypeFiles(ESData.GRWD_INDEX, date1, departId);

		// 获取今日已查看文档
		List<PublicFileQuantity> list = publicFileQuantityService.getSortByDate(date1);
		Integer viewFiles = 0;
		for (PublicFileQuantity publicFileQuantity : list) {
			viewFiles = viewFiles + publicFileQuantity.getViews();
		}

		// 获取已用空间
		List<PublicFile> list1 = publicFileService.getFiles(departId);
		// 获取用户上传数量top10
		List<PublicFileDto> list2 = publicFileMapper.getUpSortByUser(departId);
		// 获取角色上传数量
		List<PublicFileDto> list3 = publicFileMapper.getUpSortByRole(departId);

		String picture = "png,jpeg,jpg,gif,tif,bmp,webp,ico";
		String file = "pdf,docx,doc,txt,ppt,pptx,xlsx,xls";
		String video = "mp4,mpeg,avi,navi,asf,mov,3gp,wmv,divx,xvid,rm,rmvb,flv,f4v";
		String audio = "mp3,flac,wav,flac";

		Integer num1 = 0, num11 = 0;
		Integer num2 = 0, num12 = 0;
		Integer num3 = 0, num13 = 0;
		Integer num4 = 0, num14 = 0;
		Integer num5 = 0, num15 = 0;

		BigDecimal sizeAll = new BigDecimal(0);
		for (PublicFile publicFile : list1) {
			sizeAll = sizeAll.add(new BigDecimal(publicFile.getFileSize()));

			if (file.indexOf(publicFile.getSuffix()) != -1) {
				num1 = num1 + 1;
				num11 = num11 + Integer.parseInt(publicFile.getFileSize());
			} else if (picture.indexOf(publicFile.getSuffix()) != -1) {
				num2 = num2 + 1;
				num12 = num12 + Integer.parseInt(publicFile.getFileSize());
			} else if (video.indexOf(publicFile.getSuffix()) != -1) {
				num3 = num3 + 1;
				num13 = num13 + Integer.parseInt(publicFile.getFileSize());
			} else if (audio.indexOf(publicFile.getSuffix()) != -1) {
				num4 = num4 + 1;
				num14 = num14 + Integer.parseInt(publicFile.getFileSize());
			} else {
				num5 = num5 + 1;
				num15 = num15 + Integer.parseInt(publicFile.getFileSize());
			}
		}

		// 数据类型可指定
		int[] args = { num1, num2, num3, num4, num5 };
		int max = args[0];// 假设第一个值为最大值
		for (int i = 1; i < args.length; i++) { // 和后面的数进行比较
			if (args[i] > max) {
				max = args[i];
			}
		}

		BigDecimal divide1 = new BigDecimal("1024");
		BigDecimal divide2 = new BigDecimal("1024").multiply(new BigDecimal("1024"));
		BigDecimal divide3 = new BigDecimal("1024").multiply(new BigDecimal("1024").multiply(new BigDecimal("1024")));
		Double d1 = sizeAll.divide(divide1, 2, BigDecimal.ROUND_HALF_UP).doubleValue();
		Double d2 = sizeAll.divide(divide2, 2, BigDecimal.ROUND_HALF_UP).doubleValue();
		Double d3 = sizeAll.divide(divide3, 2, BigDecimal.ROUND_HALF_UP).doubleValue();

		BigDecimal mix1 = new BigDecimal(num11 + num12 + num13 + num14 + num15);
		Double d11 = 0.0, d12 = 0.0, d13 = 0.0, d14 = 0.0, d15 = 0.0;
		if (num11 > 0) {
			d11 = new BigDecimal(num11).divide(mix1, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100))
					.doubleValue();
		}
		if (num12 > 0) {
			d12 = new BigDecimal(num12).divide(mix1, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100))
					.doubleValue();
		}
		if (num13 > 0) {
			d13 = new BigDecimal(num13).divide(mix1, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100))
					.doubleValue();
		}
		if (num14 > 0) {
			d14 = new BigDecimal(num14).divide(mix1, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100))
					.doubleValue();
		}
		if (num15 > 0) {
			d15 = new BigDecimal(num15).divide(mix1, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100))
					.doubleValue();
		}

		String list11 = "";
		String list12 = "";
		for (int i = 0; i < list2.size(); i++) {
			PublicFileDto publicFile = list2.get(i);
			User user = iUserService.getById(publicFile.getCreateuserId());
			list11 = list11 + user.getNickName();
			list12 = list12 + publicFile.getFileSize();
			if (i < list2.size() - 1) {
				list11 = list11 + ",";
				list12 = list12 + ",";
			}
		}

		String list31 = "";
		String list32 = "";
		for (int i = 0; i < list3.size(); i++) {
			PublicFileDto publicFile = list3.get(i);
			list31 = list31 + publicFile.getCreateuserName();
			list32 = list32 + publicFile.getFileSize();
			if (i < list3.size() - 1) {
				list31 = list31 + ",";
				list32 = list32 + ",";
			}
		}

		String list41 = "", list42 = "", list43 = "", list44 = "";
		String yz_time = getTimeInterval(new Date());// 获取本周时间
		String array[] = yz_time.split(",");
		String start_time = array[0];// 本周第一天
		String end_time = array[1]; // 本周最后一天
		// 格式化日期
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Date dBegin = sdf.parse(start_time);
		Date dEnd = sdf.parse(end_time);
		List<Date> lDate = findDates(dBegin, dEnd);// 获取这周所有date
		for (int o = 0; o < lDate.size(); o++) {
			list41 = list41 + sdf.format(lDate.get(o)).substring(5, 10).replaceAll("-", "月") + "日";
			int upnum = publicFileService.getSortByDate(sdf.format(lDate.get(o)));
			list42 = list42 + upnum;
			List<PublicFileQuantity> list4 = publicFileQuantityService.getSortByDate(sdf.format(lDate.get(o)));
			int downloads = 0, views = 0;
			for (PublicFileQuantity publicFileQuantity : list4) {
				downloads = downloads + publicFileQuantity.getDownloads();
				views = views + publicFileQuantity.getViews();
			}
			list43 = list43 + downloads;
			list44 = list44 + views;
			if (o < lDate.size() - 1) {
				list41 = list41 + ",";
				list42 = list42 + ",";
				list43 = list43 + ",";
				list44 = list44 + ",";
			}
		}

		map.put("wdzl", count1 + count2);
		if (d1 == 0) {
			map.put("sizeAll", "0KB");
		} else if (d1 < 1) {
			map.put("sizeAll", "1KB");
		} else if (d1 >= 1) {
			map.put("sizeAll", d1.toString() + "KB");
		}
		if (d2 > 0) {
			map.put("sizeAll", d2.toString() + "MB");
		}
		if (d3 > 1) {
			map.put("sizeAll", d3.toString() + "GB");
		}
		map.put("upFiles", count3 + count4);
		map.put("viewFiles", viewFiles);
		map.put("topName", list11);
		map.put("topNum", list12);
		map.put("topMaxNum1", max);
		map.put("topNum1", num1 + "," + num2 + "," + num3 + "," + num4 + "," + num5);
		map.put("topName2", "文档,图片,视频,音频,其他");
		map.put("topNum2", d11 + "," + d12 + "," + d13 + "," + d14 + "," + d15);
		map.put("topName3", list31);
		map.put("topNum3", list32);
		map.put("topNum41", list41);
		map.put("topNum42", list42);
		map.put("topNum43", list43);
		map.put("topNum44", list44);
		return map;
	}

	/**
	 * @title 根据当前日期获得所在周的日期区间（周一和周日日期）
	 * @param date
	 * @return
	 */
	public String getTimeInterval(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		// 判断要计算的日期是否是周日，如果是则减一天计算周六的，否则会出问题，计算到下一周去了
		int dayWeek = cal.get(Calendar.DAY_OF_WEEK);// 获得当前日期是一个星期的第几天
		if (1 == dayWeek) {
			cal.add(Calendar.DAY_OF_MONTH, -1);
		}
		// System.out.println("要计算日期为:" + sdf.format(cal.getTime())); // 输出要计算日期
		// 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
		cal.setFirstDayOfWeek(Calendar.MONDAY);
		// 获得当前日期是一个星期的第几天
		int day = cal.get(Calendar.DAY_OF_WEEK);
		// 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
		cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);// 格式化日期
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String imptimeBegin = sdf.format(cal.getTime());
		// System.out.println("所在周星期一的日期：" + imptimeBegin);
		cal.add(Calendar.DATE, 6);
		String imptimeEnd = sdf.format(cal.getTime());
		// System.out.println("所在周星期日的日期：" + imptimeEnd);
		return imptimeBegin + "," + imptimeEnd;
	}

	/**
	 * @title 获取一周开始到结束的list集合
	 * @param dBegin
	 * @param dEnd
	 * @return
	 */
	public static List<Date> findDates(Date dBegin, Date dEnd) {
		List<Date> lDate = new ArrayList<>();
		lDate.add(dBegin);
		Calendar calBegin = Calendar.getInstance();
		// 使用给定的 Date 设置此 Calendar 的时间
		calBegin.setTime(dBegin);
		Calendar calEnd = Calendar.getInstance();
		// 使用给定的 Date 设置此 Calendar 的时间
		calEnd.setTime(dEnd);
		// 测试此日期是否在指定日期之后
		while (dEnd.after(calBegin.getTime())) {
			// 根据日历的规则，为给定的日历字段添加或减去指定的时间量
			calBegin.add(Calendar.DAY_OF_MONTH, 1);
			lDate.add(calBegin.getTime());
		}
		return lDate;
	}

}
